package com.laiyuezs.sdk2x;

import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.ProposalException;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;

/**
 * 主要是配合 fabric2.2.x 版本使用
 *
 * @author : 州长在手 2021/7/7 下午4:27
 */
public class ChaincodeLifecycle {

    /**
     * 安装链码
     */
    public static String lifecycleInstallChaincode(Channel channel, HFClient hfClient, String chaincodeLabel, String chaincodeSourceLocation, String chaincodePath, String metadataSourcePath) throws IOException, InvalidArgumentException, ProposalException {
        LifecycleChaincodePackage lifecycleChaincodePackage = LifecycleChaincodePackage.fromSource(
                chaincodeLabel,
                Paths.get(chaincodeSourceLocation), // GOPATH
                TransactionRequest.Type.GO_LANG,
                chaincodePath,
                Paths.get(metadataSourcePath));
        LifecycleInstallChaincodeRequest installProposalRequest = hfClient.newLifecycleInstallChaincodeRequest();
        installProposalRequest.setLifecycleChaincodePackage(lifecycleChaincodePackage);
        installProposalRequest.setProposalWaitTime(200000);
        Collection<LifecycleInstallChaincodeProposalResponse> responses = hfClient.sendLifecycleInstallChaincodeRequest(installProposalRequest, channel.getPeers());
        String packageID = null;
        for (LifecycleInstallChaincodeProposalResponse response : responses) {
            if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
                if (packageID == null) {
                    packageID = response.getPackageId();
                }
            }
        }
        return packageID;
    }

    // 新型安装链码，需要借助peer进行tar打包
    public static String lifecycleInstallChaincode(Channel channel, HFClient hfClient, LifecycleChaincodePackage lifecycleChaincodePackage) throws InvalidArgumentException, ProposalException {
        LifecycleInstallChaincodeRequest installProposalRequest = hfClient.newLifecycleInstallChaincodeRequest();
        installProposalRequest.setLifecycleChaincodePackage(lifecycleChaincodePackage);
        installProposalRequest.setProposalWaitTime(200000);
        Collection<LifecycleInstallChaincodeProposalResponse> responses = hfClient.sendLifecycleInstallChaincodeRequest(installProposalRequest, channel.getPeers());
        String packageID = null;
        for (LifecycleInstallChaincodeProposalResponse response : responses) {
            if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
                if (packageID == null) {
                    packageID = response.getPackageId();
                }
            }
        }

        return packageID;

    }


    // 通过原始数据自己打包
    public static LifecycleChaincodePackage newLifecycleChaincodePackage(
            String chaincodeLabel, // "marbles01_private",
            String chaincodeSourceLocation, // "/home/ct/go",
            String chaincodePath, // "github.com/hyperledger/fabric-samples/chaincode/marbles02_private/go",
            // META-INF
            String metadataSourcePath // "/home/ct/go/src/github.com/hyperledger/fabric-samples/chaincode/marbles02_private/go"
    ) throws IOException, InvalidArgumentException {
        return LifecycleChaincodePackage.fromSource(
                chaincodeLabel,
                Paths.get(chaincodeSourceLocation), // GOPATH
                TransactionRequest.Type.GO_LANG,
                chaincodePath,
                Paths.get(metadataSourcePath));
    }

    // 通过peer打包数据
    // CHAINCODEPATH=github.com/hyperledger/fabric-samples/chaincode/marbles02_private/go
    // CHAINCODENAME=fabcar
    // VERSION=0.1
    // ./peer  lifecycle chaincode package ${CHAINCODENAME}.tar.gz --path ${CHAINCODEPATH}  --lang golang  --label ${CHAINCODENAME}_${VERSION}
    public static LifecycleChaincodePackage newLifecycleChaincodePackage(InputStream inputStream) throws IOException, InvalidArgumentException {
        return LifecycleChaincodePackage.fromStream(inputStream);
    }


    /*
LifecycleApproveChaincodeDefinitionForMyOrgRequest
                lifecycleApproveChaincodeDefinitionForMyOrgRequest = //  好长的类型
                org.getClient().newLifecycleApproveChaincodeDefinitionForMyOrgRequest();
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setSequence(1);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeName(chaincodeName);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeVersion(chaincodeVersion);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setInitRequired(true);
 */

    /**
     * 审批链码
     */
    public static String lifecycleApproveChaincode(Channel channel, HFClient hfClient, String packageID, String chaincodeName, String chaincodeVersion, ChaincodeCollectionConfiguration chaincodeCollectionConfiguration, LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy, Integer sequence) throws InvalidArgumentException, ProposalException, InterruptedException, ExecutionException, TimeoutException {
        LifecycleApproveChaincodeDefinitionForMyOrgRequest
                lifecycleApproveChaincodeDefinitionForMyOrgRequest = //  好长的类型
                hfClient.newLifecycleApproveChaincodeDefinitionForMyOrgRequest();
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setSequence(sequence);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeName(chaincodeName);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeVersion(chaincodeVersion);
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setInitRequired(true);
        //   ChaincodeCollectionConfiguration.fromYamlFile(new File("src/test/fixture/collectionProperties/PrivateDataIT.yaml")),
        if (null != chaincodeCollectionConfiguration) {
            lifecycleApproveChaincodeDefinitionForMyOrgRequest.
                    setChaincodeCollectionConfiguration(chaincodeCollectionConfiguration);

        }
        // //Org1 also creates the endorsement policy for the chaincode. // also known as validationParameter !
        //        LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy = LifecycleChaincodeEndorsementPolicy.fromSignaturePolicyYamlFile(Paths.get(TEST_FIXTURES_PATH +
        //                "/sdkintegration/chaincodeendorsementpolicy.yaml"));
        if (null != chaincodeEndorsementPolicy) {
            lifecycleApproveChaincodeDefinitionForMyOrgRequest.
                    setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
        }
        lifecycleApproveChaincodeDefinitionForMyOrgRequest.setPackageId(packageID);


        Collection<LifecycleApproveChaincodeDefinitionForMyOrgProposalResponse>
                lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse =
                channel.sendLifecycleApproveChaincodeDefinitionForMyOrgProposal(
                        lifecycleApproveChaincodeDefinitionForMyOrgRequest, channel.getPeers());
        return channel.sendTransaction(lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse).get(3200, TimeUnit.SECONDS).getTransactionID();
    }

    /**
     * 提交链码
     */
    public static String lifecycleCommitChaincode(Channel channel, HFClient hfClient, String chaincodeName, String chaincodeVersion, Boolean InitRequired, ChaincodeCollectionConfiguration chaincodeCollectionConfiguration, LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy, Integer sequence) throws InvalidArgumentException, ProposalException, InterruptedException, ExecutionException, TimeoutException {
        LifecycleCommitChaincodeDefinitionRequest
                lifecycleCommitChaincodeDefinitionRequest = hfClient.newLifecycleCommitChaincodeDefinitionRequest();
        lifecycleCommitChaincodeDefinitionRequest.setSequence(sequence);
        lifecycleCommitChaincodeDefinitionRequest.setChaincodeName(chaincodeName);
        lifecycleCommitChaincodeDefinitionRequest.setChaincodeVersion(chaincodeVersion);
        //  lifecycleCommitChaincodeDefinitionRequest.setInitRequired(true);
        if (null != chaincodeEndorsementPolicy) {
            lifecycleCommitChaincodeDefinitionRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
        }
        if (null != chaincodeCollectionConfiguration) {
            lifecycleCommitChaincodeDefinitionRequest.setChaincodeCollectionConfiguration(chaincodeCollectionConfiguration);
        }
        lifecycleCommitChaincodeDefinitionRequest.setInitRequired(InitRequired);
        Collection<LifecycleCommitChaincodeDefinitionProposalResponse>
                lifecycleCommitChaincodeDefinitionProposalResponses =
                channel.sendLifecycleCommitChaincodeDefinitionProposal(
                        lifecycleCommitChaincodeDefinitionRequest,
                        channel.getPeers());
        return channel.sendTransaction(lifecycleCommitChaincodeDefinitionProposalResponses).get(32000, TimeUnit.SECONDS).getTransactionID();
    }

    /**
     * 第一次执行链码
     */
    public static String lifecycleInitChaincode(Channel channel, HFClient hfClient, String chaincodeName, User userContest, String initFunc, String... args) throws InvalidArgumentException, ProposalException, InterruptedException, ExecutionException, TimeoutException {

        TransactionProposalRequest transactionProposalRequest = hfClient.newTransactionProposalRequest();
        transactionProposalRequest.setChaincodeName(chaincodeName);
        transactionProposalRequest.setChaincodeLanguage(TransactionRequest.Type.GO_LANG);
        transactionProposalRequest.setUserContext(userContest);
        transactionProposalRequest.setFcn(initFunc);
        transactionProposalRequest.setProposalWaitTime(20000);
        transactionProposalRequest.setArgs(args);
        transactionProposalRequest.setInit(true);


        Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposal(transactionProposalRequest, channel.getPeers());
        Collection<ProposalResponse> successful = new LinkedList<>();
        for (ProposalResponse response : transactionPropResp) {
            if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
                successful.add(response);
            }
        }
        return channel.sendTransaction(successful).get(32000, TimeUnit.SECONDS).getTransactionID();
    }

//    /**
//     *  更新链码
//     */
//
//    public static  String lifecycleUpdateChaincode(){
//
//        return "";
//    }

}
